#include <stdio.h>

#include "stm32f10x.h"

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "event_groups.h"

void UART1_Init()
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    // 使能 GPIOA 和 USART1 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1,
                           ENABLE);

    // 配置 USART1 Tx (PA9) 为复用推挽输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置 USART1 参数
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl =
        USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);

    // 使能 USART1
    USART_Cmd(USART1, ENABLE);
}

// 重定向 fputc 函数
int fputc(int ch, FILE *f)
{
    // 等待发送缓冲区为空
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
        ;

    // 发送字符
    USART_SendData(USART1, (uint8_t)ch);

    return ch;
}

// ******************************** 队列 **************************************

// 消费者任务
void demo1_consumer_task(void *pvParameters) {
    QueueHandle_t xQueue = (QueueHandle_t)pvParameters;
    uint32_t ulReceivedValue;

    for (;;) {
        // 从队列接收数据
        if (xQueueReceive(xQueue, &ulReceivedValue, portMAX_DELAY) == pdTRUE) {
            printf("Received: %lu\n", (unsigned long)ulReceivedValue);
        }
    }
}

// 生产者任务
void demo1_producer_task(void *pvParameters) {
    QueueHandle_t xQueue = (QueueHandle_t)pvParameters;

    xTaskCreate(demo1_consumer_task, "Consumer", 128, xQueue, 1, NULL);

    uint32_t ulValue = 0;

    for (;;) {
        // 发送数据到队列， 如果队列满了，再send会阻塞
        xQueueSend(xQueue, &ulValue, portMAX_DELAY);
        ulValue++;
        vTaskDelay(pdMS_TO_TICKS(100)); // 每秒发送一次
    }
}

void demo1() {
    // 创建队列（长度10，每个元素4字节）
    QueueHandle_t xQueue = xQueueCreate(10, sizeof(uint32_t));

    // 创建任务
    xTaskCreate(demo1_producer_task, "Producer", 128, xQueue, 1, NULL);
}

// ******************************** 二进制信号量 ********************************

// 接收任务
void demo2_receiver_task(void *pvParameters) {
    SemaphoreHandle_t xBinarySemaphore = (SemaphoreHandle_t)pvParameters;

    for (;;) {
        // 等待信号量，如果没有give, take就一直等
        xSemaphoreTake(xBinarySemaphore, portMAX_DELAY);
        printf("Signal received!\n");
    }
}

// 发送任务
void demo2_sender_task(void *pvParameters) {
    SemaphoreHandle_t xBinarySemaphore = (SemaphoreHandle_t)pvParameters;

    xTaskCreate(demo2_receiver_task, "Receiver", 128, xBinarySemaphore, 1, NULL);

    for (;;) {
        // 模拟事件发生
        vTaskDelay(pdMS_TO_TICKS(100));

        // 释放信号量, 如果已经give了，还没take, 可以继续give, 不会阻塞
        xSemaphoreGive(xBinarySemaphore);
        printf("Signal sent!\n");
    }
}

void demo2()
{
    // 创建二进制信号量
    SemaphoreHandle_t xBinarySemaphore = xSemaphoreCreateBinary();

    // 创建任务
    xTaskCreate(demo2_sender_task, "Sender", 128, xBinarySemaphore, 1, NULL);
}

// ******************************** 互斥锁 **************************************


// 高优先级任务
void demo3_high_priorityTask(void *pvParameters) {
    SemaphoreHandle_t xMutex = (SemaphoreHandle_t)pvParameters;

    for (;;) {
        // 获取互斥锁
        xSemaphoreTake(xMutex, portMAX_DELAY);

        printf("demo3_high_priorityTask: %d\n", xTaskGetTickCount());

        // 释放互斥锁
        xSemaphoreGive(xMutex);

        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

// 低优先级任务
void demo3_low_priority_task(void *pvParameters) {
    SemaphoreHandle_t xMutex = (SemaphoreHandle_t)pvParameters;

    xTaskCreate(demo3_high_priorityTask, "High", 128, xMutex, 3, NULL);

    for (;;) {
        // 获取互斥锁
        xSemaphoreTake(xMutex, portMAX_DELAY);

        // 模拟长时间操作
        vTaskDelay(pdMS_TO_TICKS(500));

        // 释放互斥锁
        xSemaphoreGive(xMutex);

        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

void demo3() {
    // 创建互斥锁
    SemaphoreHandle_t xMutex = xSemaphoreCreateMutex();

    xTaskCreate(demo3_low_priority_task, "Low", 128, xMutex, 1, NULL);
}

// ******************************** 递归互斥锁 **********************************

// 嵌套函数
void demo4_nested_function(SemaphoreHandle_t xRecursiveMutex) {
    // 再次获取递归互斥锁
    xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY);
    printf("Nested function acquired mutex\n");

    // 释放递归互斥锁
    xSemaphoreGiveRecursive(xRecursiveMutex);
}

// 高优先级任务
void demo4_high_priorityTask(void *pvParameters) {
    SemaphoreHandle_t xRecursiveMutex = (SemaphoreHandle_t)pvParameters;

    for (;;) {
        // 获取递归互斥锁
        xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY);

        printf("demo4_high_priorityTask: %d\n", xTaskGetTickCount());

        // 释放递归互斥锁
        xSemaphoreGiveRecursive(xRecursiveMutex);

        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

// 任务函数
void demo4_low_priority_task(void *pvParameters) {
    SemaphoreHandle_t xRecursiveMutex = (SemaphoreHandle_t)pvParameters;

    xTaskCreate(demo4_high_priorityTask, "High", 128, xRecursiveMutex, 3, NULL);

    for (;;) {
        // 获取递归互斥锁
        xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY);
        printf("Task acquired mutex\n");

        // 调用嵌套函数
        demo4_nested_function(xRecursiveMutex);

        // 模拟长时间操作
        vTaskDelay(pdMS_TO_TICKS(500));

        // 释放递归互斥锁
        xSemaphoreGiveRecursive(xRecursiveMutex);

        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

void demo4() {
    // 创建递归互斥锁
    SemaphoreHandle_t xRecursiveMutex = xSemaphoreCreateRecursiveMutex();

    xTaskCreate(demo4_low_priority_task, "Low", 128, xRecursiveMutex, 1, NULL);
}

// ******************************** 任务通知 ************************************

// 通知任务
void demo5_notifier_task(void *pvParameters) {
    TaskHandle_t xTaskToNotify = (TaskHandle_t)pvParameters;

    for (;;) {
        // 发送通知（递增目标任务的通知值）
        vTaskDelay(pdMS_TO_TICKS(100));
        xTaskNotifyGive(xTaskToNotify);
        printf("Notification sent!\n");
    }
}

// 接收通知的任务
void demo5_receiver_task(void *pvParameters) {
    xTaskCreate(demo5_notifier_task, "Notifier", 128,
                xTaskGetCurrentTaskHandle(), 1, NULL);

    for (;;) {
        // 等待通知（清除通知值）
        vTaskDelay(pdMS_TO_TICKS(200));

        // 获取通知值，如果没有，就阻塞，如果有则返回对方give的次数，并清0
        uint32_t ulNotifiedValue = ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        printf("Notification received: %lu\n", ulNotifiedValue);
    }
}

void demo5() {
    xTaskCreate(demo5_receiver_task, "Receiver", 128, NULL, 1, NULL);
}

// ******************************** 事件组 **************************************

// 任务1：设置事件1
void demo6_task1(void *pvParameters) {
    EventGroupHandle_t xEventGroup = (EventGroupHandle_t)pvParameters;

    for (;;) {
        vTaskDelay(pdMS_TO_TICKS(600));
        xEventGroupSetBits(xEventGroup, 0x01);
        printf("Event 1 set\n");
    }
}

// 任务2：设置事件2
void demo6_task2(void *pvParameters) {
    EventGroupHandle_t xEventGroup = (EventGroupHandle_t)pvParameters;

    for (;;) {
        vTaskDelay(pdMS_TO_TICKS(1000));
        xEventGroupSetBits(xEventGroup, 0x02);
        printf("Event 2 set\n");
    }
}

// 任务3：等待事件1和事件2
void demo6_test3(void *pvParameters) {
    EventGroupHandle_t xEventGroup = (EventGroupHandle_t)pvParameters;

    EventBits_t uxBits;

    for (;;) {
        // 等待两个事件同时发生（逻辑与）
        uxBits = xEventGroupWaitBits(
            xEventGroup,
            0x01 | 0x02,
            pdTRUE,  // 退出前清除这些位
            pdTRUE,  // 逻辑与
            portMAX_DELAY
        );

        printf("Both events received: 0x%02X\n", uxBits);
    }
}

void demo6() {
    EventGroupHandle_t xEventGroup = xEventGroupCreate();

    xTaskCreate(demo6_task1, "Task1", 128, xEventGroup, 1, NULL);
    xTaskCreate(demo6_task2, "Task2", 128, xEventGroup, 1, NULL);
    xTaskCreate(demo6_test3, "Task3", 128, xEventGroup, 1, NULL);
}

// ******************************** 定时器 **************************************
void demo7_timer_callback(TimerHandle_t xTimer)
{
    // 获取定时器名称
    const char *timerName = pcTimerGetName(xTimer);

    // 获取定时器周期（单位：tick）
    TickType_t period = xTimerGetPeriod(xTimer);

    // 获取定时器下一次触发的时间点
    TickType_t expiryTime = xTimerGetExpiryTime(xTimer);

    // 获取用户设置的 ID（可以用来区分不同定时器或传递上下文）
    void *timerID = pvTimerGetTimerID(xTimer);

    // 判断定时器是否处于活动状态
    BaseType_t isActive = xTimerIsTimerActive(xTimer);

    printf("Timer Name: %s\n", timerName);
    printf("Period (ticks): %lu\n", (unsigned long)period);
    printf("Expiry Time (tick): %lu\n", (unsigned long)expiryTime);
    printf("Timer ID: %p\n", timerID);
    printf("Is Active: %s\n", isActive ? "Yes" : "No");
}

void demo7()
{
    // 定义定时器ID（可以是任意指针或整数）
    static int timerId = 123;

    // 创建定时器：名称、周期（单位：tick）、是否自动重载、ID、回调函数
    TimerHandle_t xTimer =
        xTimerCreate("MyTimer",          // 定时器名称（用于调试）
                     pdMS_TO_TICKS(500), // 周期时间（500ms）
                     pdTRUE,             // 自动重载（周期性定时器）
                     &timerId,           // 用户自定义ID（可用来区分多个定时器）
                     demo7_timer_callback // 回调函数
        );

    if (xTimer != NULL)
    {
        // 启动定时器
        xTimerStart(xTimer, 0);

        printf("Timer started.\n");
    }
    else
    {
        printf("Failed to create timer.\n");
    }
}

int main()
{
    UART1_Init();

    // demo1();
    // demo2();
    // demo3();
    // demo4();
    // demo5();
    // demo6();
    demo7();

    vTaskStartScheduler();
}

// MessageBuffer, 需要一次读完，如果读取所用空间不够大， 剩余的会被丢弃
// StreamBuffer, 可以多次读取
